#include "core/full-dyn.hpp"
#include "yocto/code/unroll.hpp"

namespace FastMD  {
	
	FullDynamics:: FullDynamics( ) throw() :
	Dynamics()
	{
	}
	
	FullDynamics:: ~FullDynamics() throw()
	{
	}
	
	
	
	void FullDynamics:: eval( Frame &frame, Potential &potential, bool isothermal ) throw()
	{
		assert( frame.particles > 0 );
		assert( frame.pbc_r != NULL );
		assert( frame.pbc_f != NULL );
		
		const size_t  n        = frame.particles;
		const Vector &position = frame[ Frame::POSITIONS     ];
		Vector       &force    = frame[ Frame::ACCELERATIONS ];
		PBC_Proc      pbc_f    = frame.pbc_f;
		const V3D    &box      = frame.box;
		const V3D    &ibox     = frame.ibox;
		Real          V        = 0;
		V3D           f_ij;
		
		//----------------------------------------------------------------------
		//-- initialize all forces
		//----------------------------------------------------------------------
		force.ldz();
		
		//----------------------------------------------------------------------
		//-- accumulate forces
		//----------------------------------------------------------------------
		for( size_t i=0; i < n; ++i )
		{
			const V3D &r_i = position[i];
			V3D       &f_i = force[i];
			for( size_t j=i+1;j<n; ++j )
			{
				const V3D &r_j = position[j];
				V3D        r_ij(r_i,r_j);
				V3D       &f_j = force[j];
				
				pbc_f(r_ij,box,ibox);
				V += potential(f_ij,r_ij);
				f_i.sub( f_ij );
				f_j.add( f_ij );
			}
		}
		
		//----------------------------------------------------------------------
		//-- update forces to accelerations
		//----------------------------------------------------------------------
		if( isothermal )
		{
			frame.thermal_friction();
		}
		frame.forces_to_accelerations();
		frame.V = V;
	}
	
}


